home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 8 / The Arsenal Files Collection #8 (Arsenal Computer) (1996).ISO / prg_gen / euphor14.zip / IMAGE.E < prev    next >
Text File  |  1996-05-20  |  10KB  |  348 lines

  1. -- Graphical Image routines
  2.  
  3. include graphics.e
  4.  
  5. constant BMPFILEHDRSIZE = 14
  6. constant OLDHDRSIZE = 12, NEWHDRSIZE = 40
  7. constant EOF = -1
  8.  
  9. -- error codes returned by read_bitmap()
  10. global constant BMP_OPEN_FAILED = 1,
  11.         BMP_UNEXPECTED_EOF = 2,
  12.         BMP_UNSUPPORTED_FORMAT = 3
  13.      
  14. integer fn, error_code
  15.  
  16. function get_word()
  17.     integer lower, upper
  18.     
  19.     lower = getc(fn)
  20.     upper = getc(fn)
  21.     if upper = EOF then
  22.     error_code = BMP_UNEXPECTED_EOF
  23.     end if
  24.     return upper * 256 + lower
  25. end function
  26.  
  27. function get_dword()
  28.     integer lower, upper
  29.     
  30.     lower = get_word()
  31.     upper = get_word()
  32.     return upper * 65536 + lower
  33. end function
  34.  
  35. function get_c_block(integer num_bytes)
  36.     sequence s
  37.     
  38.     s = repeat(0, num_bytes)
  39.     for i = 1 to num_bytes do
  40.     s[i] = getc(fn)
  41.     end for
  42.     if s[length(s)] = EOF then
  43.     error_code = BMP_UNEXPECTED_EOF
  44.     end if
  45.     return s
  46. end function
  47.  
  48. function get_rgb(integer set_size)
  49. -- get red, green, blue palette values
  50.     integer red, green, blue
  51.     
  52.     blue = getc(fn)
  53.     green = getc(fn)
  54.     red = getc(fn)
  55.     if set_size = 4 then
  56.     if getc(fn) then
  57.     end if
  58.     end if
  59.     return {red, green, blue}
  60. end function
  61.  
  62. function get_rgb_block(integer num_dwords, integer set_size)
  63. -- reads palette 
  64.     sequence s
  65.  
  66.     s = {}
  67.     for i = 1 to num_dwords do
  68.     s = append(s, get_rgb(set_size))
  69.     end for
  70.     if s[length(s)][3] = EOF then
  71.     error_code = BMP_UNEXPECTED_EOF
  72.     end if
  73.     return s
  74. end function
  75.  
  76. function row_bytes(atom BitCount, atom Width)
  77.     return floor(((BitCount * Width) + 31) / 32) * 4
  78. end function
  79.  
  80. function unpack(sequence image, integer BitCount, integer Width, integer Height)
  81. -- unpack the 1-d byte sequence into a 2-d sequence of pixels
  82.     sequence pic_2d, row, bits
  83.     integer bytes, next_byte, byte
  84.     
  85.     pic_2d = {}
  86.     bytes = row_bytes(BitCount, Width)
  87.     next_byte = 1
  88.     for i = 1 to Height do
  89.     row = {}
  90.     if BitCount = 1 then
  91.         for j = 1 to bytes do
  92.         byte = image[next_byte]
  93.         next_byte = next_byte + 1
  94.         bits = repeat(0, 8)
  95.         for k = 8 to 1 by -1 do
  96.             bits[k] = remainder(byte, 2)
  97.             byte = floor(byte/2)
  98.         end for
  99.         row = row & bits
  100.         end for
  101.     elsif BitCount = 2 then
  102.         for j = 1 to bytes do
  103.         byte = image[next_byte]
  104.         next_byte = next_byte + 1
  105.         bits = repeat(0, 4)
  106.         for k = 4 to 1 by -1 do
  107.             bits[k] = remainder(byte, 4)
  108.             byte = floor(byte/4)
  109.         end for
  110.         row = row & bits
  111.         end for
  112.     elsif BitCount = 4 then
  113.         for j = 1 to bytes do
  114.         byte = image[next_byte]
  115.         row = append(row, floor(byte/16))
  116.         row = append(row, remainder(byte, 16))
  117.         next_byte = next_byte + 1
  118.         end for
  119.     elsif BitCount = 8 then
  120.         row = row & image[next_byte..next_byte+bytes-1]
  121.         next_byte = next_byte + bytes
  122.     else
  123.         error_code = BMP_UNSUPPORTED_FORMAT
  124.         exit
  125.     end if
  126.     pic_2d = prepend(pic_2d, row[1..Width])
  127.     end for
  128.     return pic_2d
  129. end function
  130.  
  131. without warning
  132. global function read_bitmap(sequence file_name)
  133. -- read a bitmap (.BMP) file into a 2-d sequence of sequences (image)
  134. -- return {palette,image}   
  135.     atom Size 
  136.     integer Type, Xhot, Yhot, Planes, BitCount
  137.     atom Width, Height, Compression, OffBits, SizeHeader, 
  138.      SizeImage, XPelsPerMeter, YPelsPerMeter, ClrUsed,
  139.      ClrImportant, NumColors
  140.     sequence Palette, Bits, two_d_bits
  141.  
  142.     error_code = 0
  143.     fn = open(file_name, "rb")
  144.     if fn = -1 then
  145.     return BMP_OPEN_FAILED
  146.     end if
  147.     Type = get_word()
  148.     Size = get_dword()
  149.     Xhot = get_word()
  150.     Yhot = get_word()
  151.     OffBits = get_dword()
  152.     SizeHeader = get_dword()
  153.  
  154.     if SizeHeader = NEWHDRSIZE then
  155.     Width = get_dword()
  156.     Height = get_dword()
  157.     Planes = get_word()
  158.     BitCount = get_word()
  159.     Compression = get_dword()
  160.     if Compression != 0 then
  161.         return BMP_UNSUPPORTED_FORMAT
  162.     end if
  163.     SizeImage = get_dword()
  164.     XPelsPerMeter = get_dword()
  165.     YPelsPerMeter = get_dword()
  166.     ClrUsed = get_dword()
  167.     ClrImportant = get_dword()
  168.     NumColors = (OffBits - SizeHeader - BMPFILEHDRSIZE) / 4
  169.     if NumColors < 2 or NumColors > 256 then
  170.         return BMP_UNSUPPORTED_FORMAT
  171.     end if
  172.     Palette = get_rgb_block(NumColors, 4) 
  173.     
  174.     elsif SizeHeader = OLDHDRSIZE then 
  175.     Width = get_word()
  176.     Height = get_word()
  177.     Planes = get_word()
  178.     BitCount = get_word()
  179.     NumColors = (OffBits - SizeHeader - BMPFILEHDRSIZE) / 3
  180.     SizeImage = row_bytes(BitCount, Width) * Height
  181.     Palette = get_rgb_block(NumColors, 3) 
  182.     else
  183.     return BMP_UNSUPPORTED_FORMAT
  184.     end if
  185.     if Planes != 1 then
  186.     return BMP_UNSUPPORTED_FORMAT
  187.     end if
  188.     Bits = get_c_block(row_bytes(BitCount, Width) * Height)
  189.     close(fn)
  190.     two_d_bits = unpack(Bits, BitCount, Width, Height)
  191.     if error_code then
  192.     return error_code 
  193.     end if
  194.     return {Palette, two_d_bits}
  195. end function
  196. with warning
  197.  
  198. type graphics_point(sequence p)
  199.     return length(p) = 2 and p[1] >= 0 and p[2] >= 0
  200. end type
  201.  
  202. type text_point(sequence p)
  203.     return length(p) = 2 and p[1] >= 1 and p[2] >= 1 
  204.        and p[1] <= 200 and p[2] <= 500 -- rough sanity check
  205. end type
  206.  
  207. global procedure display_image(graphics_point xy, sequence pixels)
  208. -- display a 2-d sequence of pixels at location xy
  209. -- N.B. coordinates are {x, y} with {0,0} at top left of screen
  210. -- and x values increasing towards the right, 
  211. -- and y values increasing towards the bottom of the screen
  212.     for i = 1 to length(pixels) do
  213.     pixel(pixels[i], xy)
  214.     xy[2] = xy[2] + 1
  215.     end for
  216. end procedure
  217.  
  218. global function save_image(graphics_point top_left, graphics_point bottom_right)
  219. -- Save a rectangular region on a graphics screen,
  220. -- given the {x, y} coordinates of the top-left and bottom-right 
  221. -- corner pixels. The result is a 2-d sequence of pixels suitable 
  222. -- for use in display_image() above.
  223.     integer x, width
  224.     sequence save
  225.     
  226.     x = top_left[1]
  227.     width = bottom_right[1] - x + 1
  228.     save = {}
  229.     for y = top_left[2] to bottom_right[2] do
  230.     save = append(save, get_pixel({x, y, width}))
  231.     end for
  232.     return save
  233. end function
  234.  
  235. constant COLOR_TEXT_MEMORY = #B8000,
  236.       MONO_TEXT_MEMORY = #B0000
  237.  
  238. constant M_GET_DISPLAY_PAGE = 28,
  239.      M_SET_DISPLAY_PAGE = 29,
  240.      M_GET_ACTIVE_PAGE = 30,
  241.      M_SET_ACTIVE_PAGE = 31
  242.  
  243. constant BYTES_PER_CHAR = 2
  244.  
  245. type page_number(integer p)
  246.     return p >= 0 and p <= 7
  247. end type
  248.  
  249. global function get_display_page()
  250. -- return current page# mapped to the monitor   
  251.     return machine_func(M_GET_DISPLAY_PAGE, 0)
  252. end function
  253.  
  254. global procedure set_display_page(page_number page)
  255. -- select a page to be displayed
  256.     machine_proc(M_SET_DISPLAY_PAGE, page)
  257. end procedure
  258.  
  259. global function get_active_page()
  260. -- return current page# that screen output is sent to
  261.     return machine_func(M_GET_ACTIVE_PAGE, 0)
  262. end function
  263.  
  264. global procedure set_active_page(page_number page)
  265. -- select a page for screen output
  266.     machine_proc(M_SET_ACTIVE_PAGE, page)
  267. end procedure
  268.  
  269. global procedure display_text_image(text_point xy, sequence text)
  270. -- Display a text image at line xy[1], column xy[2] in any text mode.
  271. -- N.B. coordinates are {line, column} with {1,1} at the top left of screen
  272. -- Displays to the active text page. Image must fit on screen.
  273.     atom screen_memory, scr_addr
  274.     integer screen_width, extra_col2, extra_lines
  275.     sequence vc
  276.     
  277.     vc = video_config()
  278.     if vc[VC_MODE] = 7 then
  279.     screen_memory = MONO_TEXT_MEMORY
  280.     else
  281.     screen_memory = COLOR_TEXT_MEMORY
  282.     end if
  283.     screen_width = vc[VC_COLUMNS]
  284.     if screen_width = 40 then
  285.     screen_memory = screen_memory + get_active_page() * 2048
  286.     else
  287.     screen_memory = screen_memory + get_active_page() * 4096
  288.     end if
  289.     
  290.     if xy[1] < 1 or xy[2] < 1 then
  291.     return -- bad starting point
  292.     end if
  293.     extra_lines = vc[VC_LINES] - xy[1] + 1 
  294.     if length(text) > extra_lines then
  295.     if extra_lines <= 0 then
  296.         return -- nothing to display
  297.     end if
  298.     text = text[1..extra_lines] -- truncate
  299.     end if
  300.     scr_addr = screen_memory + (xy[1]-1) * screen_width * BYTES_PER_CHAR
  301.                  + (xy[2]-1) * BYTES_PER_CHAR
  302.     extra_col2 = 2 * (vc[VC_COLUMNS] - xy[2] + 1) 
  303.     for row = 1 to length(text) do
  304.     if length(text[row]) > extra_col2 then
  305.         if extra_col2 <= 0 then
  306.         return -- nothing to display
  307.         end if
  308.         text[row] = text[row][1..extra_col2] -- truncate
  309.     end if
  310.     poke(scr_addr, text[row])
  311.     scr_addr = scr_addr + screen_width * BYTES_PER_CHAR
  312.     end for
  313. end procedure
  314.  
  315. global function save_text_image(text_point top_left, text_point bottom_right)
  316. -- Copy a rectangular block of text out of screen memory,
  317. -- given the coordinates of the top-left and bottom-right corners.
  318. -- Reads from the active text page.
  319.     sequence image, row_chars, vc
  320.     atom scr_addr, screen_memory
  321.     integer screen_width, image_width
  322.     
  323.     vc = video_config()
  324.     if vc[VC_MODE] = 7 then
  325.     screen_memory = MONO_TEXT_MEMORY
  326.     else
  327.     screen_memory = COLOR_TEXT_MEMORY
  328.     end if
  329.     screen_width = vc[VC_COLUMNS]
  330.     if screen_width = 40 then
  331.     screen_memory = screen_memory + get_active_page() * 2048
  332.     else
  333.     screen_memory = screen_memory + get_active_page() * 4096
  334.     end if
  335.     scr_addr = screen_memory + 
  336.            (top_left[1]-1) * screen_width * BYTES_PER_CHAR + 
  337.            (top_left[2]-1) * BYTES_PER_CHAR
  338.     image = {}
  339.     image_width = bottom_right[2] - top_left[2] + 1
  340.     for row = top_left[1] to bottom_right[1] do
  341.     row_chars = peek({scr_addr, image_width*BYTES_PER_CHAR})
  342.     image = append(image, row_chars)
  343.     scr_addr = scr_addr + screen_width * BYTES_PER_CHAR
  344.     end for
  345.     return image
  346. end function
  347.  
  348.